﻿#include "ncspropmgr_p.h"
#include "ncspropedit.h"
#include "ncsprop_utils.h"
#include "stringlisteditor/ncsstringlistedit.h"

//#include <QApplication>
#include <QDebug>
#include <QFontDatabase>

#include <algorithm>

namespace utils {

static inline QColor valueColor(NcsColorProp* color_prop)
{
    int r = color_prop->subProperties()[0]->value().toInt();
    int g = color_prop->subProperties()[1]->value().toInt();
    int b = color_prop->subProperties()[2]->value().toInt();
    int a = color_prop->subProperties()[3]->value().toInt();

    return QColor(r, g, b, a);
}

} // namespace utils 

//--------------------------------------------------------------------------------------------------NcsProp

NcsProp::NcsProp(NcsPropMgr *manager):
    d(new NcsPropPrivate(this))
{
    d->mgr = manager;
}

NcsProp::~NcsProp()
{
    if (d) {
		delete d;
        d = nullptr; 
    }
}

const QList<NcsProp *>& NcsProp::subProperties() const { return d->m_subprops; }

NcsPropMgr* NcsProp::propMgr() const {return d->mgr;}

// Label that displayed in front of the prop editor. 
QString NcsProp::label() const  { return d->label; }
void NcsProp::setLabel(const QString &text) { d->label = text; }

int NcsProp::propType() const { return d->m_proptype; }

QVariant NcsProp::value() const { return d->val; }

QVariant NcsProp::getAttrib(const QString& attrib_name) 
{
    auto it =  d->m_attrib.constFind(attrib_name);
    if (it == d->m_attrib.constEnd())
        return QVariant();
    else
        return it.value(); 
}

void NcsProp::setAttrib(const QString& attrib_name, QVariant attrib_value) 
{
    d->m_attrib[attrib_name] = attrib_value; 
}

//! prop是否已经分配了non-null 值. 
bool NcsProp::hasValue() const 
{
    return ! d->val.isNull();
}

/*
  将一个prop添加到子属性列表中. 注意需要修改prop的parent属性. 
 */
void NcsProp::addSubProperty(NcsProp *prop)
{
    // check duplicity
    if (d->m_subprops.indexOf(prop) != -1)  return; 
    if (prop->d->parent())
        prop->d->parent()->removeSubProperty(prop); 

    d->m_subprops.append(prop);
    prop->d->m_parent = this; 
}

void NcsProp::insertSubProperty(NcsProp *pp, NcsProp *pp_after)
{
    // check duplicity
    if (!pp || d->m_subprops.indexOf(pp) != -1)  return; 
    int pos = d->m_subprops.indexOf(pp_after) + 1;
    // remove from old parent's sub-props list. 
    if (pp->d->parent())
        pp->d->parent()->removeSubProperty(pp); 
    d->m_subprops.insert(pos, pp);
    pp->d->m_parent = this; 

    emit d->mgr->propertyInserted(pp, this, pp_after);
}

void NcsProp::removeSubProperty(NcsProp *pp)
{
    int index = d->m_subprops.indexOf(pp);
    if (index == -1) return; 
    d->m_subprops.removeAt(index); 

    emit d->mgr->propertyRemoved(pp, this);
}

bool NcsProp::status(PropStatus status_code) const         { return d->status(status_code); }
void NcsProp::setStatus(PropStatus status_code, bool f_set) { d->setStatus(status_code, f_set); }
void NcsProp::clearStatus()                                { d->clearStatus(); }

//! Set property value to {val} WITHOUT type cheking, so its only for private usage. 
bool NcsProp::setVariantValue(QVariant val) 
{
    if (this->outofRange(val))
        val = this->restrictInRange(val);

    if (d->val != val)
    {
        d->val = val;
        d->clearStatus();
        d->setStatus ( PS_MODIFIED , true); 
        
        emit d->mgr->valueChanged(this, d->val);
#ifndef NDEBUG
        qDebug() << QString("Property Chaneged : [%1 : ").arg(this->label()) << d->val;
#endif
        return true;
    }
    return false; 
}

//! rewrite property type.  for derived class only
void NcsProp::setPropType(int prop_type)
{
    d->setPropType(prop_type); 
}

void NcsPropExt::modifyPropValue(NcsProp* p, QVariant val)
{
    val = p->restrictInRange(val); 
    p->d->val = val;
}

//----------------------------------------------------------------------------------------NcsColorProp {

NcsColorProp::NcsColorProp(NcsPropMgr *manager) : NcsProp(manager) 
{
    this->setPropType(NcsPropMgr::colorTypeId());

    // add sub-properties, default font is (0, 0, 0, 255)
    NcsProp* red_prop = manager->addProperty(NcsPropMgr::intTypeId(), QObject::tr("Red")); 
    dynamic_cast<NcsIntProp*>(red_prop)->setRange(0, 255); 
    NcsPropExt::modifyPropValue(red_prop, QVariant(0));
    this->addSubProperty(red_prop);

    NcsProp* green_prop = manager->addProperty(NcsPropMgr::intTypeId(), QObject::tr("Green")); 
    dynamic_cast<NcsIntProp*>(green_prop)->setRange(0, 255); 
    NcsPropExt::modifyPropValue(green_prop, QVariant(0));
    this->addSubProperty(green_prop);

    NcsProp* blue_prop = manager->addProperty(NcsPropMgr::intTypeId(), QObject::tr("Blue")); 
    dynamic_cast<NcsIntProp*>(blue_prop)->setRange(0, 255); 
    NcsPropExt::modifyPropValue(blue_prop, QVariant(0));
    this->addSubProperty(blue_prop);
    
    NcsProp* alpha_prop = manager->addProperty(NcsPropMgr::intTypeId(), QObject::tr("Alpha")); 
    dynamic_cast<NcsIntProp*>(alpha_prop)->setRange(0, 255); 
    NcsPropExt::modifyPropValue(alpha_prop, QVariant(255));
    this->addSubProperty(alpha_prop);

} // NcsColorProp }


//----------------------------------------------------------------------------------------NcsFontProp {

NcsFontProp::NcsFontProp(NcsPropMgr *manager) : NcsProp(manager) 
{
    this->setPropType(NcsPropMgr::fontTypeId());
    
    // add sub-properties, default font is [simsun, 9]
    // should be string enum
    NcsProp* family = manager->addProperty(NcsPropMgr::stringEnumTypeId(), QObject::tr("Family")); 
	QStringList families = manager->getFontFamilies();
	dynamic_cast<NcsStringEnumProp*>(family)->setOptions(families);
	for (auto font_name : families)
	{
		if (font_name.contains("microsoft yahei", Qt::CaseInsensitive) ||
			font_name.contains("yahei ui", Qt::CaseInsensitive) ||
			font_name.contains("stheiti", Qt::CaseInsensitive) ||
			font_name.contains("simsun", Qt::CaseInsensitive)
			)
		{
            NcsPropExt::modifyPropValue(family, font_name);  // set font to the first found one. 
			break; 
		}
	}

    if (!family->hasValue())
        NcsPropExt::modifyPropValue(family, families[0]);  // set font to the first one. 

    this->addSubProperty(family);
    manager->setEditorFactory(family, [=](NcsProp* prop) -> QWidget* {
            QStringList families = manager->getFontFamilies(); 
            dynamic_cast<NcsStringEnumProp*>(prop)->setOptions(families); 
            NcsStringEnumEdit* npcombo = new NcsStringEnumEdit(prop);
			npcombo->setItemAndData(families);
            return npcombo; 
        } );

    NcsProp* pointsize = manager->addProperty(NcsPropMgr::intTypeId(), QObject::tr("Point Size")); 
    dynamic_cast<NcsIntProp*>(pointsize)->setRange(1, INT_MAX); 
    NcsPropExt::modifyPropValue(pointsize, QVariant(12));
    this->addSubProperty(pointsize);

    NcsProp* bold = manager->addProperty(NcsPropMgr::boolTypeId(), QObject::tr("Bold")); 
    NcsPropExt::modifyPropValue(bold, false);
    this->addSubProperty(bold);

    NcsProp* italic = manager->addProperty(NcsPropMgr::boolTypeId(), QObject::tr("Italic")); 
    NcsPropExt::modifyPropValue(italic, false);
    this->addSubProperty(italic);
    
    NcsProp* underline = manager->addProperty(NcsPropMgr::boolTypeId(), QObject::tr("Underline")); 
    NcsPropExt::modifyPropValue(underline, false);
    this->addSubProperty(underline);

    NcsProp* strikeout = manager->addProperty(NcsPropMgr::boolTypeId(), QObject::tr("Strikeout")); 
    NcsPropExt::modifyPropValue(strikeout, false);
    this->addSubProperty(strikeout);

    NcsProp* kerning = manager->addProperty(NcsPropMgr::boolTypeId(), QObject::tr("Kerning")); 
    NcsPropExt::modifyPropValue(kerning, false);
    this->addSubProperty(kerning);
    
    // should be string enum / int enum
    NcsProp* antialiasing = manager->addProperty(NcsPropMgr::intEnumTypeId(), QObject::tr("Antialiasing")); 
    dynamic_cast<NcsEnumProp*>(antialiasing)->setOptions 
        ( 
         { "Default style", "No antialias", "Antialias if possible"}, 
         { QFont::PreferDefault, QFont::NoAntialias,QFont::PreferAntialias} 
        );

    NcsPropExt::modifyPropValue(antialiasing, QFont::PreferDefault); 
    //NcsPropExt::modifyPropValue(antialiasing, "no-antialiasing"); 
    this->addSubProperty(antialiasing);


} // NcsFontProp::NcsFontProp 

bool NcsFontProp::updateFromSubProps()  
{
    QFont val;
    val.setFamily    ( this->subProp (0)->value ().toString ());
    val.setPointSize ( this->subProp (1)->value ().toInt    ());
    val.setBold      ( this->subProp (2)->value ().toBool   ());
    val.setItalic    ( this->subProp (3)->value ().toBool   ());
    val.setUnderline ( this->subProp (4)->value ().toBool   ());
    val.setStrikeOut ( this->subProp (5)->value ().toBool   ());
    val.setKerning   ( this->subProp (6)->value ().toBool   ());
    this->setVariantValue(val);

    return true; 
} // NcsFontProp::updateFromSubProps

// NcsFontProp }


//----------------------------------------------------------------------------------------NcsEnumProp {
NcsEnumProp::NcsEnumProp(NcsPropMgr *manager) : NcsProp(manager)
{
    this->setPropType(NcsPropMgr::intEnumTypeId()); // NcsEnumProp is of integer type by default. 
}

bool NcsEnumProp::setOptions(const QStringList& option_labels, QVariantList option_data )
{
    m_option_labels.clear();
    m_option_data.clear();

    if (option_data.isEmpty()) {
        if (this->propType() == NcsPropMgr::intEnumTypeId())
        {
            for (int i = 0; i < option_labels.size(); ++i)
                option_data.push_back(i);
        }
        else if (this->propType() == NcsPropMgr::stringEnumTypeId())
        {
            for (auto p : option_labels)
                option_data.append(p);
        }
        else
        {
            qFatal("Strange emum type. ");
        }
    }

    if (option_labels.size() != option_data.size() && option_labels.size() == 0)
        qFatal("Item labels and data are not match or empty. ");

    m_option_labels = option_labels;
    m_option_data = option_data;
    return true;
}

bool NcsEnumProp::setVariantValue(QVariant val) 
{
    if (this->getIndexFromValue(val) != -1)
    //if (!m_option_labels.isEmpty() && val.toInt() < m_option_labels.size())
    {
        NcsProp::setVariantValue(val);
        return true;
    }

    qDebug() << QString("NcsEnumProp::setValue() : "\
        "Input value '%1' is not a valid option.")
        .arg(val.toInt());

    return false;
}

//NcsEnumProp }

//----------------------------------------------------------------------------------------NcsStringEnumProp {

NcsStringEnumProp::NcsStringEnumProp(NcsPropMgr *manager) : NcsEnumProp(manager)
{
    this->setPropType(NcsPropMgr::stringEnumTypeId());
}

bool NcsStringEnumProp::setVariantValue(QVariant val) 
{
    if (this->getIndexFromValue(val) != -1)
    //if (!m_option_labels.isEmpty() && m_option_labels.contains(val.toString()))
    {
        NcsProp::setVariantValue(val);
        return true;
    }

    qDebug() << QString( "NcsStringEnumProp::setValue() : " \
        "Input string '%1' is not a valid option value. Label: '%2'")
        .arg(val.toString()).arg(this->label());


    return false;
}

// NcsStringEnumProp }

//--------------------------------------------------------------------------------------------------NcsPropMgr

NcsPropMgr::NcsPropMgr(QObject *parent):
    d (new NcsPropMgrPrivate(this))
{
	setDefaultTypeEditor();
    connect(this, &NcsPropMgr::valueChanged, this, &NcsPropMgr::slotParentAutoUpdate); 
}

NcsPropMgr::~NcsPropMgr()
{
    if (d) {
        delete d;
        d = nullptr; 
    }
}

NcsProp* NcsPropMgr::addProperty(int prop_type, const QString &label, 
            EditorFn fn_edit_creator, 
            DecoratorFn decorator)
{
    NcsProp* prop = nullptr; 

    if (prop_type == intTypeId())
        prop = NcsPropExt::create<NcsIntProp>(this);
    else if (prop_type == doubleTypeId())
        prop = NcsPropExt::create<NcsDoubleProp>(this);
    else if (prop_type == colorTypeId())
        prop = NcsPropExt::create<NcsColorProp>(this);
    else if (prop_type == fontTypeId())
        prop = NcsPropExt::create<NcsFontProp>(this);
    else if (prop_type == stringEnumTypeId())
        prop = new  NcsStringEnumProp(this); 
    else if (prop_type == intEnumTypeId())
        prop = new  NcsIntEnumProp(this); 
    else
        prop = new NcsProp(this);  // ordinary types of property.  string, stringlist, etc. 


    prop->d->m_proptype = prop_type; 
    prop->setLabel(label);
    if (fn_edit_creator)
        setPropFactoryFn(prop, fn_edit_creator);

    this->addPropertyToMgr(prop);
   
    return prop;
}

int NcsPropMgr::removeProperty(NcsProp* p)
{
    int num_removed = 0; 
    if (!p) return num_removed; 
    
    // remove the sub properties.  
    if (p->subProperties().size() > 0)
    {
        auto subprops = p->subProperties(); // copy sub properties. 
        for (auto subp : subprops)
            num_removed += this->removeProperty(subp); 
    }

    if (p->d->parent()) 
        p->d->parent()->removeSubProperty(p);  // remove property's pointer only, the memory has not been released. 

    // remove properties editor factory. 
    d->prop_factory.remove(p) ;
    d->prop_decrator.remove(p) ;

   emit propertyDestroying(p) ;
    if (d->m_deletebehavior == DELETE_DIRECTLY )
        delete p;
    else
        d->cacheAdd(p);

    return 1; 
}

QStringList NcsPropMgr::getFontFamilies()
{
    // start font db watcher
    d->startFontChangeWatcher();  
    return d->m_fontfamilies; 
}


void NcsPropMgr::setEditorFactory(NcsProp* prop, EditorFn editor_fn) 
{
 	d->prop_factory[prop] = editor_fn; 
}

NcsProp* NcsPropMgr::rootProp() const { return & d->m_root; }


void NcsPropMgr::setDeleteBehavior(DeleteBehavior  behavior)
{
    d->m_deletebehavior = behavior;
}

NcsPropMgr::DeleteBehavior NcsPropMgr::deleteBehaivior() const { return d->m_deletebehavior; }

bool NcsPropMgr::setValue(NcsProp *prop, bool    val)
{
    if (prop->propType() != boolTypeId() ) 
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires bool value!";
        abort();
    }

	prop->setVariantValue(val);
    return true; 
}

bool NcsPropMgr::setValue(NcsProp *prop, int    val)
{
    if (prop->propType() != intTypeId() && prop->propType() != intEnumTypeId() ) 
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires int as value!";
        abort();
    }

	prop->setVariantValue(val);
    //property->d->val = val; 
    return true; 
}

bool NcsPropMgr::setValue(NcsProp *prop, double val)
{
    if (prop->propType() != doubleTypeId() ) 
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires double precision number as value!";
        abort();
    }

	prop->setVariantValue(val);
    //prop->d->val = val; 
    return true; 
}

bool NcsPropMgr::setValue(NcsProp *prop, const QString& val)
{
    if ( prop->propType() != stringTypeId()     &&  
         prop->propType() != stringEnumTypeId() &&  
        prop->propType()  != doubleTypeId() ) 
    {
        qDebug() << "NcsPropMgr::setValue() : Incompatible property type to string value!";
        abort();
    }

    if (prop->propType() == doubleTypeId())
    {
        bool ok =false; 
        double dbl_val =  val.toDouble(&ok);
        if (!ok) { 
            prop->uninitialize(); 
            return false;
        }
    }

    return prop->setVariantValue(val);
}

bool NcsPropMgr::setValue(NcsProp *prop, const QStringList& val)
{
    if (prop->propType() != stringListTypeId() )
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires string list as value!";
        abort();
    }

	prop->setVariantValue(val);
    //prop->d->val = val; 
    return true; 
}

bool NcsPropMgr::setValue(NcsProp *prop, const QColor& val)
{
    if (prop->propType() != colorTypeId() )
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires QColor as value!";
        abort();
    }

    prop->subProp(0)->setVariantValue(val.red()); 
    prop->subProp(1)->setVariantValue(val.green()); 
    prop->subProp(2)->setVariantValue(val.blue()); 
    prop->subProp(3)->setVariantValue(val.alpha()); 

    // modify value text
    NcsPropExt::modifyPropValue(prop, val);
    return true; 
}

bool NcsPropMgr::setValue(NcsProp *prop, const QFont& val)
{
    if (prop->propType() != fontTypeId() )
    {
        qDebug()<<"NcsPropMgr::setValue() : Property requires QFont as value!";
        abort();
    }

    prop->subProp(0)->setVariantValue(val.family()); 
    prop->subProp(1)->setVariantValue(val.pointSize()); 
    prop->subProp(2)->setVariantValue(val.bold()); 
    prop->subProp(3)->setVariantValue(val.italic()); 
    prop->subProp(4)->setVariantValue(val.underline()); 
    prop->subProp(5)->setVariantValue(val.strikeOut()); 
    prop->subProp(6)->setVariantValue(val.kerning()); 

    NcsPropExt::modifyPropValue(prop, val);
    return true; 
}


bool NcsPropMgr::slotParentAutoUpdate(NcsProp* sub_prop, const QVariant& val) 
{
    NcsProp* parent = sub_prop->d->parent();
    if (parent == nullptr || parent == rootProp() || parent->propType() == groupTypeId()) 
        return false;

    if (parent->propType() == colorTypeId())
    {
        QColor color = utils::valueColor(dynamic_cast<NcsColorProp*>(parent));
        this->setVariantValue(parent, color);
        return true; 
    }
    else if (parent->propType() == fontTypeId())
    {
        parent->updateFromSubProps();
        return true;
    }

    return false; 
}

QString NcsPropMgr::valueText(const NcsProp* prop) const
{
    if (prop->propType() == this->intTypeId()) {
        return QString::number(prop->value().toInt());
    }
    else if (prop->propType() == this->intEnumTypeId() || prop->propType() == stringEnumTypeId()) {
        const NcsEnumProp* enum_prop = dynamic_cast<const NcsEnumProp*>(prop);
        return enum_prop->currentLabel();
    }
    else if (prop->propType() == this->doubleTypeId()) {
        if (prop->value().type() == QVariant::String)
            return prop->value().toString();
        else
            return QString::number(prop->value().toDouble()); 
    }
    else if (prop->propType() == this->stringTypeId()) {
        return prop->value().toString();
    }
    else if (prop->propType() == this->stringListTypeId()) {
        return prop->value().toStringList().join(", ");
    }
    else if (prop->propType() == this->boolTypeId()) {
        return prop->value().toBool() ? tr("True") : tr("False");
    }
    else if (prop->propType() == this->colorTypeId()) {
        QColor color =  prop->value().value<QColor>(); 
        return QString("[%1, %2, %3](%4)")
            .arg(color.red())
            .arg(color.green())
            .arg(color.blue())
            .arg(color.alpha());
    }
    else if (prop->propType() == this->fontTypeId()) {
        QFont font =  prop->value().value<QFont>(); 
        return QString("[%1, %2]")
            .arg(font.family())
            .arg(font.pointSize());
    }

    else
        qDebug() << "NcsPropMgr::valueText() : unknown property type " << prop->propType();

    return prop->value().toString();
}

QIcon NcsPropMgr::valueIcon(const NcsProp* prop) const
{
    if (prop->propType() == boolTypeId())
    {
        return utils::createCheckBoxIcon(prop->value().toBool());
    }
    if (prop->propType() == colorTypeId())
    {
        int r = prop->subProperties()[0]->value().toInt(); 
        int g = prop->subProperties()[1]->value().toInt(); 
        int b = prop->subProperties()[2]->value().toInt();
        int a = prop->subProperties()[3]->value().toInt();

        //const NcsColorProp* clrp = dynamic_cast<const NcsColorProp*>(prop);

        QPixmap pixmap(16, 16);
        pixmap.fill(QColor(r, g, b, a));
        return QIcon(pixmap);
    }
    if (prop->propType() == fontTypeId())
    {
        QPixmap pxmap = utils::createPixmapFromFont(prop->value().value<QFont>()) ;
        return QIcon(pxmap); 
    }

    return QIcon(); 
}

//! Set property value to {val} WITHOUT type cheking, so its only for private usage. 
bool NcsPropMgr::setVariantValue(NcsProp* prop, QVariant val) 
{
    return prop->setVariantValue(val); 
}

void NcsPropMgr::initializeProperty(NcsProp* prop)
{
    if (! prop)  return; 
    prop->d->val = QVariant();
}

void NcsPropMgr::uninitializeProperty(NcsProp* prop)
{
    if (! prop)  return; 
    prop->d->val = QVariant();
}


void NcsPropMgr::setTypeEditorFactoryFn(int prop_type, EditorFn editor_factory)
{
    if (d->type_factory.contains(prop_type))
        qWarning()<<"Warning : type factor is overwrite for type " << prop_type; 

    d->type_factory[prop_type] = editor_factory; 
}

void NcsPropMgr::setPropFactoryFn(NcsProp* prop, EditorFn editor_factory)
{
    d->prop_factory[prop] = editor_factory; 
}


void NcsPropMgr::addPropertyToMgr(NcsProp* prop)
{
    d->m_root.addSubProperty(prop); 
}

#include <QLineEdit>
#include <QComboBox>
#include <QCheckBox>
#include <QDoubleValidator>

void NcsPropMgr::setDefaultTypeEditor ()
{
	// bool type
	d->type_factory[boolTypeId()] = [](NcsProp* prop) {
        NpBoolEdit* edit = new NpBoolEdit(prop); 
        return edit; 
	};

	// int type
	d->type_factory[intTypeId()] = [](NcsProp* prop) {
        return new NpIntEdit(prop); 
	};

    // double type
	d->type_factory[doubleTypeId()] = [](NcsProp* prop) {
       return new NpDoubleEdit(prop); 
	};

    // string type
	d->type_factory[stringTypeId()] = [](NcsProp* prop) {
        return new NpStringEdit(prop);
        //return edit; 
	};

	d->type_factory[fontTypeId()] = [](NcsProp* prop) {
        return new NcsFontEdit(prop);
        //return edit; 
	};

	d->type_factory[colorTypeId()] = [](NcsProp* prop) {
        return new NcsColorEdit(prop);
	};

    // stringlist type
	d->type_factory[stringListTypeId()] = [](NcsProp* prop) {
        QWidget *edit = new NcsStringListEdit(prop);
        return edit; 
	};

    // string enum type
    d->type_factory[stringEnumTypeId()] = [](NcsProp* prop) -> QWidget* {
        NpComboBox* combo = new NcsStringEnumEdit(prop, nullptr);
        NcsStringEnumProp* prop_strenum = dynamic_cast<NcsStringEnumProp*>(prop);
        if (prop_strenum) {
            combo->setItemAndData(prop_strenum->optionLabels(), prop_strenum->optionData());
        }
        return combo;
    };

    // int enum type
    d->type_factory[intEnumTypeId()] = [](NcsProp* prop) -> QWidget* {
        NpComboBox* combo = new NcsIntEnumEdit(prop, nullptr);
        NcsIntEnumProp* prop_strenum = dynamic_cast<NcsIntEnumProp*>(prop);
        if (prop_strenum) {
            combo->setItemAndData(prop_strenum->optionLabels(), prop_strenum->optionData());
        }
        return combo;
    };
}

//--------------------------------------------------------------------------------------------------

void NcsPropMgrPrivate::startFontChangeWatcher()
{
    // start font db watcher
    if (!m_fontDBChangeTimer)
    {
        slotFontDBDelayedChange();  // get all font families ready. 
        if (!m_fontDBChangeTimer) {
            m_fontDBChangeTimer = new QTimer(q);
            m_fontDBChangeTimer->setInterval(0);
            m_fontDBChangeTimer->setSingleShot(true);
            //QObject::connect(m_fontDBChangeTimer, SIGNAL(timeout()), q_ptr, SLOT(slotFontDBDelayedChange()));
            QObject::connect(m_fontDBChangeTimer, & QTimer::timeout, 
                [this]() { slotFontDBDelayedChange(); });
        }
        if (!m_fontDBChangeTimer->isActive())
            m_fontDBChangeTimer->start();
    }
}

Q_GLOBAL_STATIC(QFontDatabase, fontDatabase); 

void NcsPropMgrPrivate::slotFontDBDelayedChange()
{
    // rescan available font names
    const QStringList oldFamilies = m_fontfamilies;
    m_fontfamilies= fontDatabase()->families();

    //! @todo once font families are updated, all the created font editor's should be updated to.
    
}
